package com.iwhalecloud.citybrain.flow.platform.manager.application.service;

import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.FlowTaskTraceVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowTaskService;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
　　* @description: 流程基础数据处理
　　* @author shenrm
　　* @date 2021/11/10 9:57
　　*/
@Component
public class FlowBaseDataHandleProcessor {

    /**
     * 日志类
     */
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private FlowTaskService flowTaskService;

    @Autowired
    private HistoryService historyService;

    /**
     * 根据任务ID检查单个任务对象是否存在
     *
     * @param taskId
     * @return
     */
    public boolean isExistCheckSingleTask(String taskId) {
        if (StringUtils.isEmpty(taskId)) {
            logger.warn("任务ID值为空", taskId);
            return false;
        }
        Task task = this.resolveTaskSingle(taskId);
        if (Objects.isNull(task)) {
            logger.warn("任务ID不存在", taskId);
            return false;
        }
        return true;
    }

    /**
     * 根据流程实例获取并检查流程实例是否存在
     *
     * @param processInstanceId
     * @return
     */
    public boolean isExistCheckProcessInstance(String processInstanceId) {
        ProcessInstance processInstance = this.resolveProcessInstance(processInstanceId);
        if (Objects.nonNull(processInstance)) {
            return true;
        }
        return false;
    }



    /**
     * 根据任务ID检查单个任务对象是否存在
     *
     * @param taskId
     * @return
     */
    public boolean isExistCheckFlowTaskTraceByCandidate(String taskId, String userCode) {
        FlowTaskTraceVo flowTaskTraceVo = flowTaskService.getFlowTaskByTaskIdOrUserCode(taskId,userCode);
        if(Objects.isNull(flowTaskTraceVo)) {
            logger.warn("流程任务轨迹不存在任务编码{}", taskId);
            return false;
        }
        return true;
    }

    /**
     * 根据流程实例ID获取流程实例
     *
     * @param processInstanceId
     * @return
     */
    public ProcessInstance resolveProcessInstance(String processInstanceId) {
        if (StringUtils.isEmpty(processInstanceId)) {
            logger.warn("未传递流程实例id[processInstanceId]");
            return null;
        }

        // 获取流程实例对象
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (Objects.isNull(processInstance)) {
            logger.warn("流程实例{}不存在", processInstanceId);
            return null;
        }
        return processInstance;
    }

    /**
     * 根据流程实例ID获取active的流程实例
     *
     * @param processInstanceId
     * @return
     */
    public ProcessInstance resolveActiveProcessInstance(String processInstanceId) {
        if (StringUtils.isEmpty(processInstanceId)) {
            logger.warn("未传递流程实例id[processInstanceId]");
            return null;
        }

        // 获取流程实例对象
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult();
        if (Objects.isNull(processInstance)) {
            logger.warn("流程实例 {} 不存在或者已挂起", processInstanceId);
            return null;
        }
        return processInstance;
    }

    /**
     * 根据流程是咧ID以及任务ID查找流程实例以及任务实例对应的任务
     *
     * @param processInstanceId
     * @param taskId
     * @return
     */
    public Task resolveTaskByProcessInstanceIdAndTaskId(String processInstanceId, String taskId) {
        if (StringUtils.isEmpty(taskId)) {
            logger.warn("任务id,值为{}", taskId);
            return null;
        }
        // 任务实例
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).taskId(taskId).singleResult();
        if (Objects.isNull(task)) {
            logger.warn("任务不存在,任务ID:{}", taskId);
            return null;
        }
        return task;
    }

    /**
     * 根据任务ID获取单个任务对象
     *
     * @param taskId
     * @return
     */
    public Task resolveTaskSingle(String taskId) {
        return taskService.createTaskQuery().taskId(taskId).singleResult();
    }

    /**
     * 按照候选人方式获取单个任务对象信息,可以检查任务是否存在使用
     *
     * @param taskId
     * @param userCode
     * @return
     */
    public Task getTaskByCandidate(String taskId, String userCode){
        FlowTaskTraceVo flowTaskTraceVo = flowTaskService.getFlowTaskByTaskIdOrUserCode(taskId,userCode);
        if (Objects.isNull(flowTaskTraceVo)){
            return null;
        }
        return taskService.createTaskQuery().taskId(flowTaskTraceVo.getTaskId()).singleResult();
    }


    /**
     * 根据流程实例ID获取当前流程实例,当前流程实例为空,则再查询一把历史
     *
     * @param processInstanceId
     * @return
     */
    public String getDeploymentId(String processInstanceId) {
        if (StringUtils.isEmpty(processInstanceId)) {
            logger.warn("未传递流程实例id[processInstanceId]");
            return null;
        }

        // 获取流程实例对象
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();

        // 如果存在,则直接返回
        if (Objects.nonNull(processInstance)) {
            return processInstance.getDeploymentId();
        }

        // 再查询下历史任务记录
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (Objects.isNull(historicProcessInstance)) {
            logger.warn("流程实例{}不存在", processInstanceId);
            return null;
        }
        return historicProcessInstance.getDeploymentId();
    }


    /**
     * 根据流程是咧ID以及任务ID查找流程实例以及任务实例对应的任务当前任务查询不到还要查询一把历史
     *
     * @param processInstanceId
     * @param taskId
     * @return
     */
    public Task resolveHistoryTaskByPidAndTid(String processInstanceId, String taskId) {
        if (StringUtils.isEmpty(taskId)) {
            logger.warn("任务id,值为{}", taskId);
            return null;
        }
        // 任务实例
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).taskId(taskId).singleResult();

        // 如果存在,则直接返回
        if (Objects.nonNull(task)) {
            return task;
        }

        // 再查询下历史任务记录
        HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).taskId(taskId).singleResult();
        if (Objects.isNull(historicTaskInstance)) {
            logger.warn("任务不存在,任务ID:{}", taskId);
            return null;
        }
        TaskEntityImpl taskEntity = new TaskEntityImpl();
        taskEntity.setTaskDefinitionKey(historicTaskInstance.getTaskDefinitionKey());
        return taskEntity;
    }

    /**
     * 根据流程实例ID获取历史的流程实例
     *
     * @param processInstanceId
     * @return
     */
    public HistoricProcessInstance resolveHistoryProcessInstance(String processInstanceId) {
        if (StringUtils.isEmpty(processInstanceId)) {
            logger.warn("未传递流程实例id[processInstanceId]");
            return null;
        }

        // 获取流程实例对象
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (Objects.isNull(historicProcessInstance)) {
            logger.warn("流程实例{}不存在", processInstanceId);
            return null;
        }
        return historicProcessInstance;
    }

    /**
     * 根据流程是咧ID以及任务ID查找流程实例以及任务实例对应的任务
     *
     * @param taskId
     * @return
     */
    public HistoricTaskInstance resolveHistoryTaskByTaskId(String taskId) {
        if (StringUtils.isEmpty(taskId)) {
            logger.warn("任务id,值为{}", taskId);
            return null;
        }
        // 任务实例
        HistoricTaskInstance historyTask = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        if (Objects.isNull(historyTask)) {
            logger.warn("任务不存在,任务ID:{}", taskId);
            return null;
        }
        return historyTask;
    }
}
